﻿
#include "tuya_conn_mgr.h"

#include <conf_mgr.h>
// #include <data.h>
#include <wind_mgr.h>
#include "conf_mgr.h"
// #include <homewindow.h>
// #include <tuya_os_mgr.h>
#include <project.h>
#include "page_mode1.h"

#define TICK_TIME 50 // tick触发时间（毫秒）

CTuYaConnMgr *g_tuYaObjConnMgr = CTuYaConnMgr::ins();
//////////////////////////////////////////////////////////////////

CTuYaConnMgr::CTuYaConnMgr()
{
    mPacket = new SDHWPacketBuffer(BT_TUYA_MCU);
    mUartMCU = 0;
    mNextEventTime = 0;
    mLastSendTime = 0;
    mLastStatusTime = 0;
    mSetData = 0;
    mMcuType = 0;
    mLastWarnTime = 0;
    mLastBeepTime = 0;
    commErrorCount = 0;
    mIsFactory = false;
    isFirst = true;
    reqOpenWeatherFlag = false;
    mLastConnectTime = 0;

    g_objHandler->addHandler(BT_TUYA_MCU, this);
}

CTuYaConnMgr::~CTuYaConnMgr()
{
    __del(mUartMCU);
}

std::string CTuYaConnMgr::searchProductInfo()
{
    LOGE("{\"p\":\"3rnmb7mduigzd8nn\",\"v\":\"1.0.0\",\"m\":0,\"mt\":10,\"n\":0,\"ir\":\"5.12\",\"low\":0}");
    return "{\"p\":\"3rnmb7mduigzd8nn\",\"v\":\"1.0.0\",\"m\":0}";
}

int CTuYaConnMgr::init()
{
    UartOpenReq ss;

    snprintf(ss.serialPort, sizeof(ss.serialPort), "/dev/ttyS2");
    ss.speed = 9600;
    ss.flow_ctrl = 0;
    ss.databits = 8;
    ss.stopbits = 1;
    ss.parity = 'N';

    mLastWarnTime = SystemClock::uptimeMillis();
    mUartMCU = new UartClient(mPacket, BT_TUYA_MCU, ss, "10.0.0.11", 9876, 0);
    mUartMCU->init();

    // 启动延迟一会后开始发包
    mNextEventTime = SystemClock::uptimeMillis() + TICK_TIME * 10;
    App::getInstance().addEventHandler(this);

    // 静音标识
    // closeVolumn(g_objConf->getMuteFlag());

    return 0;
}

int CTuYaConnMgr::checkEvents()
{
    int64_t curr_tick = SystemClock::uptimeMillis();
    if (curr_tick >= mNextEventTime)
    {
        mNextEventTime = curr_tick + TICK_TIME;
        return 1;
    }
    return 0;
}

int CTuYaConnMgr::handleEvents()
{
    int64_t now_tick = SystemClock::uptimeMillis();

    if (mUartMCU)
        mUartMCU->onTick();

    // if (mSetData > 0 || now_tick - mLastSendTime >= 1000) { send2MCU(TUYA_WIFI_CMD_HEARTBEAT); }

    if (reqOpenWeatherFlag && now_tick - mLastConnectTime >= 10 * 1000)
    {
        // send2MCU(TUYA_WIFI_CMD_REQUEST_WEATHER);
        mLastConnectTime = now_tick;
        reqOpenWeatherFlag = !reqOpenWeatherFlag;
    }
    return 1;
}

bool CTuYaConnMgr::getVersion(int &a, int &b, int &c)
{
    if (mMcuType == 0)
        return false;
    a = mMcuType;
    return true;
}

void CTuYaConnMgr::send2MCU(TUYA_WIFI_CMD_e cmd)
{
    BuffData *bd = mPacket->obtain();
    UI2TUYA snd(bd);

    snd.setData(BUF_SND_D3, cmd);

    switch (cmd)
    {
    case TUYA_WIFI_CMD_HEARTBEAT:
    {
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x01);
        snd.setData(BUF_SND_D6, isFirst ? 0x00 : 0x01);
        if (isFirst)
        {
            isFirst = false;
        }
        break;
    }
    case TUYA_WIFI_CMD_PRODUCT_INFO:
    {
        std::string str = searchProductInfo();
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x4c);
        memcpy(mSndData, str.c_str(), str.size());

        for (int i = 0; i < str.size(); i++)
        {
            snd.setData(BUF_SND_D6 + i, mSndData[i]);
        }
        break;
    }
    case TUYA_WIFI_CMD_WORK_MODE:
    {
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x00);
        break;
    }
    case TUYA_WIFI_CMD_NETWORK_STATUS:
    {
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x00);
        break;
    }
    case TUYA_WIFI_CMD_CLOUD_CMD:
    {
        snd.setData(BUF_SND_D3, 0x07);
        break;
    }
    case TUYA_WIFI_CMD_REQUEST_TIME:
    {
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x00);
        break;
    }
    case TUYA_WIFI_CMD_OPEN_WEATHER:
    {
        int tempLen = strlen((char *)_cmd_temp); // 0x06
        mSndData[0] = tempLen;
        std::copy(_cmd_temp, _cmd_temp + tempLen, mSndData + 1);
        // for (int i = 0; i < tempLen + 1; i++)
        // {
        //     LOG(ERROR) << "mSndData[" << i << "] = " << hexstr(&mSndData[i], 1);
        // }

        int weatherLen = strlen((char *)_cmd_weather); // 0x0e
        mSndData[tempLen + 1] = weatherLen;
        std::copy(_cmd_weather, _cmd_weather + weatherLen + 1, mSndData + tempLen + 2);
        // LOGE("tempLen:%d, weatherLen:%d", tempLen, weatherLen);
        // for (int i = tempLen; i < weatherLen + 1; i++)
        // {
        //     LOG(ERROR) << "mSndData[" << i << "] = " << hexstr(&mSndData[i], 1);
        // }

        snd.setData(BUF_SND_D4, (tempLen + weatherLen + 2) >> 8 & 0xFF);
        snd.setData(BUF_SND_D5, (tempLen + weatherLen + 2) & 0xFF);
        for (int i = 0; i < tempLen + weatherLen + 2; i++)
        {
            snd.setData(BUF_SND_D6 + i, mSndData[i]);
            // LOG(ERROR) << "mSndData[" << i << "] = " << hexstr(&mSndData[i], 1);
        }
        // LOG(ERROR) << "send to mcu. bytes=" << hexstr(bd->buf, bd->len);
        break;
    }
    case TUYA_WIFI_CMD_REQUEST_WEATHER:
    {
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x01);
        snd.setData(BUF_SND_D6, 0x03);
        break;
    }
    case TUYA_WIFI_CMD_SEND_WEATHER_DATA:
    {
        snd.setData(BUF_SND_D4, 0x00);
        snd.setData(BUF_SND_D5, 0x00);
        break;
    }
    default:
        break;
    }

    // snd.checkcode(); // 修改检验位  发送之前会调用，不用额外再调一次
    mUartMCU->send(bd);

    // mLastSendTime = SystemClock::uptimeMillis();
}

void CTuYaConnMgr::onCommDeal(IAck *ack)
{
    LOG(INFO) << "hex str=" << hexstr(ack->mBuf, ack->mDlen);

    switch (ack->getCMD())
    {
    case TUYA_WIFI_CMD_HEARTBEAT:
    {
        send2MCU(TUYA_WIFI_CMD_HEARTBEAT);
        break;
    }
    case TUYA_WIFI_CMD_PRODUCT_INFO:
    {
        send2MCU(TUYA_WIFI_CMD_PRODUCT_INFO);
        break;
    }
    case TUYA_WIFI_CMD_WORK_MODE:
    {
        send2MCU(TUYA_WIFI_CMD_WORK_MODE);
        break;
    }
    case TUYA_WIFI_CMD_NETWORK_STATUS:
    {
        send2MCU(TUYA_WIFI_CMD_NETWORK_STATUS);
        if (ack->mBuf[ack->mDlen - 2] == 0x04)
        {
            send2MCU(TUYA_WIFI_CMD_REQUEST_TIME);
            send2MCU(TUYA_WIFI_CMD_OPEN_WEATHER);
            // send2MCU(TUYA_WIFI_CMD_REQUEST_WEATHER);
        }

        break;
    }
    case TUYA_WIFI_CMD_CLOUD_CMD:
    {
        onDpCommDeal(ack);
        break;
    }
    case TUYA_WIFI_CMD_REQUEST_TIME:
    {
        LOGI("获取本地时间");
        getLocalTime(ack);
        break;
    }
    case TUYA_WIFI_CMD_OPEN_WEATHER:
    {
        if (ack->mBuf[6] == 0x01 && ack->mBuf[7] == 0x00)
        {
            reqOpenWeatherFlag = true;
            LOGI("打开获取天气数据功能成功");
            send2MCU(TUYA_WIFI_CMD_REQUEST_WEATHER);
        }
        else
            LOGI("打开获取天气数据功能失败");
        break;
    }
    case TUYA_WIFI_CMD_SEND_WEATHER_DATA:
    {
        LOGI("模组下发天气数据");
        send2MCU(TUYA_WIFI_CMD_SEND_WEATHER_DATA);
        if (ack->mBuf[6] == 0x01)
        {
            getWeatherData(ack);
        }
        else
        {
            LOGI("天气数据解析失败");
        }
        break;
    }
    case TUYA_WIFI_CMD_REQUEST_WEATHER:
    {
        LOGI("主动请求天气数据返回");
        break;
    }
    default:
        break;
    }
}

void CTuYaConnMgr::onDpCommDeal(IAck *ack)
{
    uchar *aBuf = ack->mBuf;
    int aLen = ack->mDlen;
    int dpId = aBuf[BUF_RCV_D6];
    int dataLen = (aBuf[BUF_RCV_D4] << 8) | aBuf[BUF_RCV_D5];
    int funcLen = (aBuf[BUF_RCV_D8] << 8) | aBuf[BUF_RCV_D9];
    int num = 0;
    for (int i = BUF_RCV_D10; i < aLen - 1; i++)
    {
        mFunction[num++] = aBuf[i];
    }

    BuffData *bd = mPacket->obtain();
    UI2TUYA snd(bd);
    snd.setData(BUF_SND_D3, 0x07);

    switch (dpId)
    {
    case TYCMD_SWITCH:
    {
        LOGI("TYCMD_SWITCH");
        break;
    }
    case TYCMD_START_STOP:
    {
        LOGI("TYCMD_START_STOP");
        break;
    }
    case TYCMD_PAUSE_RUN:
    {
        LOGI("TYCMD_PAUSE_RUN");
        break;
    }
    case TYCMD_MODE:
    {
        LOGI("TYCMD_MODE");
        break;
    }
    default:
        LOGI("default");
        break;
    }

    for (int i = BUF_SND_D4; i < aLen - 1; i++)
    {
        snd.setData(i, ack->mBuf[i]);
    }
    snd.checkcode();
    mUartMCU->send(bd);
}

void CTuYaConnMgr::getLocalTime(IAck *ack)
{
    uchar *tBud = ack->mBuf;
    int tLen = ack->mDlen;
    if (tBud[6] != 0x01)
    {
        LOGE("获取本地时间失败");
        return;
    }

    int l = 7;
    int year = tBud[l++] + 2000;
    int month = tBud[l++];
    int day = tBud[l++];
    int hour = tBud[l++];
    int min = tBud[l++];
    int sec = tBud[l++];
    LOGI("year:%d,month:%d,day:%d,hour:%d,min:%d,sec:%d", year, month, day, hour, min, sec);
    timeSet(year, month, day, hour, min, sec);
    LOGI("获取并更新本地时间成功");
}

void CTuYaConnMgr::getWeatherData(IAck *ack)
{

    LOGI("获取天气成功    %d", 0x00);
    std::map<std::string, std::string> weatherMap;
    parseWeatherData(ack, &weatherMap);
    for(const auto &it : weatherMap)
    {
        LOGI("key:%s,value:%s",it.first.c_str(),it.second.c_str());
    }

    auto itWeather = weatherMap.find("w.temp");
    LOGI("------------------------------");
    if (itWeather != weatherMap.end())
    {
        LOGI("--------------(*itWeather).second= %d-----(*itWeather).second=%s-----------", (*itWeather).second, (*itWeather).second.c_str());
        g_appData.temperature = std::stoi((*itWeather).second);
        LOGE("g_appData.temperature:%d", g_appData.temperature);
    }
    LOGI("------------------------------");
    itWeather = weatherMap.find(std::string((char *)_cmd_weather));
    if (itWeather != weatherMap.end())
    {
        int w = std::stoi((*itWeather).second);
        auto wea = WeatherImgMap.find(w);
        LOGI("------------------------------");
        if (wea != WeatherImgMap.end())
        {
            g_appData.weather = (*wea).second.weatherImg + "_larger";
        }
        LOGE("g_appData.wearher:%s", g_appData.weather.c_str());
    }
    d_windMgr->sendMsg(PAGE_MODE1, PageMode1::MSG_UPDATE_DATA, nullptr);

    LOGI("------------------------------");
    // uchar temp[0x06] = {0x77, 0x2e, 0x74, 0x65, 0x6d, 0x70};
    // uchar weather[0x0e] = {0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d};
}

void CTuYaConnMgr::parseWeatherData(IAck *ack, std::map<std::string, std::string> *weatherMap)
{
    /**55 aa 00 21                                      请求头
     * 00 22                                            数据长度
     * 01                                               状态码 失败：0x00 成功：0x01
     * 06 77 2e 74 65 6d 70                             数据长度：0x06  数据：w.temp
     * 00                                               字段类型：0x00 整形
     * 04                                               字段长度
     * 00 00 00 18                                      字段内容
     * 0e 77 2e 63 6f 6e 64 69 74 69 6f 6e 4e 75 6d     数据长度：0x0e  数据：w.conditionNum
     * 01                                               字段类型：0x01  字符串
     * 03                                               字段长度
     * 31 33 32                                         字段内容
     * 04                                               校验和
     */
    int flag = BUF_RCV_D7;
    int len = BUF_RCV_D7;
    uchar *bd = ack->mBuf;
    std::string key = "";
    std::string value = "";
    for (len; len < ack->mDlen - 1;)
    {
        LOGI("------------------------------");
        key = "";
        value = "";
        for (int i = 0; i < bd[len]; i++)
        {
            // LOGE("bd[len]: %d", bd[len]);
            key += static_cast<char>(bd[++flag]);
            // LOGE("i: %d   key: %s", i, key.c_str());
            // LOGE("key flag: %d", flag);
        }
        // LOGE("flag: %d", flag); // 13       33
        LOGE("key: %s", key.c_str());
        // LOGI("------------------------------");
        len += bd[len] + 2; // 将 len 指向下一个长度字段        15
        if (bd[++flag] == 0x00)
        {
            int v = 0;
            ++flag;
            // LOGE("int  len: %d    bd[len]: %d", len, bd[len]);
            // LOGI("------------------------------");
            for (int j = 0; j < bd[len]; j++)
            {
                v += static_cast<int>(bd[++flag]);
                // LOGE("j: %d   v: %d", j, v);
                // LOGE("value int flag: %d", flag);
            }
            value = std::to_string(v);
        }
        else if (bd[flag] == 0x01)
        {
            ++flag;
            // LOGI("------------------------------");
            // LOGE("string  len: %d    bd[len]: %d", len, bd[len]);
            // LOGE("value string flag: %d", flag);
            // LOGE("0x01flag: %d", flag);
            // LOGI("------------------------------");
            for (int j = 0; j < bd[len]; j++)
            {
                value += static_cast<char>(bd[++flag]);
                // LOGE("i: %d   value: %s", j, value.c_str());
                // LOGE("value string flag: %d", flag);
            }
        }
        // LOGI("------------------------------");
        LOGE("value: %s", value.c_str());
        weatherMap->insert(std::make_pair(key, value));
        // LOGE("end flag: %d", flag);
        len += bd[len] + 1;         // 将 len 指向下一个数据的长度
        ++flag;
    }
}